/*!
 * \file test_wts_risk_portfolio.cpp
 * \project WonderTrader
 * 
 * \author AI Assistant
 * \date 2024/12/01
 * 
 * \brief WTS风控和组合资金管理测试文件
 * 
 * \details 本文件包含对WonderTrader风控和组合资金管理相关类的全面测试：
 *          - WTSPortFundInfo：组合资金信息管理
 *          - WTSFundStruct：资金结构体数据
 *          - TradeStatInfo：交易统计信息
 *          - 风控参数和监控功能
 *          - 资金极值跟踪和历史记录
 *          
 *          测试覆盖基本功能、边界条件、性能特性和完整工作流程
 */

#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include <thread>
#include <chrono>
#include <vector>
#include <random>
#include <algorithm>

#include "WTSRiskDef.hpp"
#include "WTSContractInfo.hpp"
#include "WTSSessionInfo.hpp"

USING_NS_WTP;

/*!
 * \brief WTS风控和组合资金管理测试类
 * 
 * \details 提供风控和资金管理相关功能的测试环境
 */
class WTSRiskPortfolioTest : public ::testing::Test {
protected:
    void SetUp() override {
        // 测试环境初始化
    }

    void TearDown() override {
        // 测试环境清理
    }
};

/*!
 * \brief 测试WTSPortFundInfo基本功能
 * 
 * \details 验证组合资金信息类的基本操作：
 *          - 对象创建和初始化
 *          - 资金信息设置和获取
 *          - 基础数据访问方法
 */
TEST_F(WTSRiskPortfolioTest, TestWTSPortFundInfoBasicOperations) {
    // 测试对象创建
    WTSPortFundInfo* fundInfo = WTSPortFundInfo::create();
    ASSERT_NE(fundInfo, nullptr);
    
    // 验证初始状态
    EXPECT_EQ(fundInfo->balance(), 0.0);
    EXPECT_EQ(fundInfo->profit(), 0.0);
    EXPECT_EQ(fundInfo->dynprofit(), 0.0);
    EXPECT_EQ(fundInfo->fees(), 0.0);
    
    // 测试资金信息设置
    WTSFundStruct& fund = fundInfo->fundInfo();
    fund._balance = 100000.0;
    fund._predynbal = 95000.0;
    fund._prebalance = 90000.0;
    fund._profit = 5000.0;
    fund._dynprofit = 2000.0;
    fund._fees = 100.0;
    fund._last_date = 20241201;
    
    // 验证数据访问
    EXPECT_DOUBLE_EQ(fundInfo->balance(), 100000.0);
    EXPECT_DOUBLE_EQ(fundInfo->predynbalance(), 95000.0);
    EXPECT_DOUBLE_EQ(fundInfo->profit(), 5000.0);
    EXPECT_DOUBLE_EQ(fundInfo->dynprofit(), 2000.0);
    EXPECT_DOUBLE_EQ(fundInfo->fees(), 100.0);
    EXPECT_EQ(fundInfo->last_settle_date(), 20241201);
    
    fundInfo->release();
}

/*!
 * \brief 测试WTSFundStruct极值跟踪功能
 * 
 * \details 验证资金结构体的极值跟踪：
 *          - 最大/最小动态权益记录
 *          - 时间戳记录
 *          - 历史极值对比
 */
TEST_F(WTSRiskPortfolioTest, TestWTSFundStructExtremeValues) {
    WTSPortFundInfo* fundInfo = WTSPortFundInfo::create();
    WTSFundStruct& fund = fundInfo->fundInfo();
    
    // 设置极值信息
    fund._max_dyn_bal = 120000.0;
    fund._max_time = 143000;
    fund._min_dyn_bal = 80000.0;
    fund._min_time = 103000;
    
    // 设置历史极值
    fund._max_md_dyn_bal._dyn_balance = 125000.0;
    fund._max_md_dyn_bal._date = 20241130;
    fund._min_md_dyn_bal._dyn_balance = 75000.0;
    fund._min_md_dyn_bal._date = 20241115;
    
    // 验证极值访问
    EXPECT_DOUBLE_EQ(fundInfo->max_dyn_balance(), 120000.0);
    EXPECT_EQ(fundInfo->max_dynbal_time(), 143000);
    EXPECT_DOUBLE_EQ(fundInfo->min_dyn_balance(), 80000.0);
    EXPECT_EQ(fundInfo->min_dynbal_time(), 103000);
    
    // 验证历史极值
    EXPECT_DOUBLE_EQ(fundInfo->max_md_dyn_balance(), 125000.0);
    EXPECT_EQ(fundInfo->max_md_dynbal_date(), 20241130);
    EXPECT_DOUBLE_EQ(fundInfo->min_md_dyn_balance(), 75000.0);
    EXPECT_EQ(fundInfo->min_md_dynbal_date(), 20241115);
    
    fundInfo->release();
}

/*!
 * \brief 测试TradeStatInfo交易统计功能
 * 
 * \details 验证交易统计信息结构：
 *          - 开平仓统计
 *          - 报单和撤单统计
 *          - 错单统计
 */
TEST_F(WTSRiskPortfolioTest, TestTradeStatInfo) {
    TradeStatInfo statInfo;
    
    // 初始化验证
    EXPECT_EQ(statInfo.l_openvol, 0);
    EXPECT_EQ(statInfo.s_openvol, 0);
    EXPECT_EQ(statInfo.l_closevol, 0);
    EXPECT_EQ(statInfo.s_closevol, 0);
    
    // 设置开平仓统计
    statInfo.l_openvol = 100;      // 多头开仓量
    statInfo.s_openvol = 80;       // 空头开仓量
    statInfo.l_closevol = 60;      // 多头平仓量
    statInfo.s_closevol = 40;      // 空头平仓量
    statInfo.l_closetvol = 20;     // 多头平今量
    statInfo.s_closetvol = 15;     // 空头平今量
    
    // 设置报单统计
    statInfo.b_orders = 50;         // 买入委托笔数
    statInfo.s_orders = 45;         // 卖出委托笔数
    statInfo.b_ordqty = 5000;       // 买入委托量
    statInfo.s_ordqty = 4500;       // 卖出委托量
    
    // 设置撤单统计
    statInfo.b_cancels = 5;         // 买入撤单笔数
    statInfo.s_cancels = 3;         // 卖出撤单笔数
    statInfo.b_canclqty = 500;      // 买入撤单量
    statInfo.s_canclqty = 300;      // 卖出撤单量
    
    // 设置错单统计
    statInfo.b_wrongs = 2;          // 买入错单笔数
    statInfo.s_wrongs = 1;          // 卖出错单笔数
    
    // 验证统计数据
    EXPECT_EQ(statInfo.l_openvol, 100);
    EXPECT_EQ(statInfo.s_openvol, 80);
    EXPECT_EQ(statInfo.l_closevol, 60);
    EXPECT_EQ(statInfo.s_closevol, 40);
    EXPECT_EQ(statInfo.l_closetvol, 20);
    EXPECT_EQ(statInfo.s_closetvol, 15);
    
    EXPECT_EQ(statInfo.b_orders, 50);
    EXPECT_EQ(statInfo.s_orders, 45);
    EXPECT_EQ(statInfo.b_ordqty, 5000);
    EXPECT_EQ(statInfo.s_ordqty, 4500);
    
    EXPECT_EQ(statInfo.b_cancels, 5);
    EXPECT_EQ(statInfo.s_cancels, 3);
    EXPECT_EQ(statInfo.b_canclqty, 500);
    EXPECT_EQ(statInfo.s_canclqty, 300);
    
    EXPECT_EQ(statInfo.b_wrongs, 2);
    EXPECT_EQ(statInfo.s_wrongs, 1);
}

/*!
 * \brief 测试WTSCommodityInfo商品信息功能
 * 
 * \details 验证商品信息类的基本功能：
 *          - 对象创建和属性设置
 *          - 交易参数配置
 *          - 品种类型判断
 */
TEST_F(WTSRiskPortfolioTest, TestWTSCommodityInfo) {
    // 创建商品信息对象
    WTSCommodityInfo* commInfo = WTSCommodityInfo::create(
        "IF", "沪深300股指期货", "CFFEX", "TRADING", "CHINA", "CNY"
    );
    ASSERT_NE(commInfo, nullptr);
    
    // 验证基本信息
    EXPECT_STREQ(commInfo->getProduct(), "IF");
    EXPECT_STREQ(commInfo->getName(), "沪深300股指期货");
    EXPECT_STREQ(commInfo->getExchg(), "CFFEX");
    EXPECT_STREQ(commInfo->getCurrency(), "CNY");
    EXPECT_STREQ(commInfo->getFullPid(), "CFFEX.IF");
    
    // 设置交易参数
    commInfo->setVolScale(300);          // 合约乘数
    commInfo->setPriceTick(0.2);         // 最小价格变动
    commInfo->setCategory(CC_Future);    // 期货类别
    commInfo->setMinLots(1.0);           // 最小交易手数
    
    // 验证交易参数
    EXPECT_EQ(commInfo->getCategoty(), CC_Future);
    EXPECT_DOUBLE_EQ(commInfo->getPriceTick(), 0.2);
    EXPECT_EQ(commInfo->getVolScale(), 300);
    EXPECT_DOUBLE_EQ(commInfo->getMinLots(), 1.0);
    
    // 测试品种类型判断
    EXPECT_TRUE(commInfo->isFuture());
    EXPECT_FALSE(commInfo->isStock());
    EXPECT_FALSE(commInfo->isOption());
    
    // 测试期权品种
    WTSCommodityInfo* optionInfo = WTSCommodityInfo::create(
        "IO", "沪深300ETF期权", "SSE", "TRADING", "CHINA", "CNY"
    );
    optionInfo->setCategory(CC_ETFOption);
    
    EXPECT_TRUE(optionInfo->isOption());
    EXPECT_FALSE(optionInfo->isFuture());
    EXPECT_FALSE(optionInfo->isStock());
    
    // 测试股票品种
    WTSCommodityInfo* stockInfo = WTSCommodityInfo::create(
        "000001", "平安银行", "SZSE", "TRADING", "CHINA", "CNY"
    );
    stockInfo->setCategory(CC_Stock);
    
    EXPECT_TRUE(stockInfo->isStock());
    EXPECT_FALSE(stockInfo->isFuture());
    EXPECT_FALSE(stockInfo->isOption());
    
    commInfo->release();
    optionInfo->release();
    stockInfo->release();
}

/*!
 * \brief 测试WTSContractInfo合约信息功能
 * 
 * \details 验证合约信息类的基本功能：
 *          - 对象创建和属性设置
 *          - 交易限制配置
 *          - 合约代码处理
 */
TEST_F(WTSRiskPortfolioTest, TestWTSContractInfo) {
    // 创建合约信息对象
    WTSContractInfo* contractInfo = WTSContractInfo::create(
        "IF2412", "沪深300股指期货2412", "CFFEX", "IF"
    );
    ASSERT_NE(contractInfo, nullptr);
    
    // 验证基本信息
    EXPECT_STREQ(contractInfo->getCode(), "IF2412");
    EXPECT_STREQ(contractInfo->getName(), "沪深300股指期货2412");
    EXPECT_STREQ(contractInfo->getExchg(), "CFFEX");
    EXPECT_STREQ(contractInfo->getProduct(), "IF");
    EXPECT_STREQ(contractInfo->getFullCode(), "CFFEX.IF2412");
    EXPECT_STREQ(contractInfo->getFullPid(), "CFFEX.IF");
    
    // 设置交易限制
    contractInfo->setVolumeLimits(100, 500);  // 市价单100手，限价单500手
    
    // 验证交易限制
    EXPECT_EQ(contractInfo->getMaxMktVol(), 100);
    EXPECT_EQ(contractInfo->getMaxLmtVol(), 500);
    
    contractInfo->release();
}

/*!
 * \brief 测试资金信息边界条件
 * 
 * \details 验证资金信息在边界条件下的行为：
 *          - 零值和负值处理
 *          - 极大值处理
 *          - 数据一致性检查
 */
TEST_F(WTSRiskPortfolioTest, TestFundInfoBoundaryConditions) {
    WTSPortFundInfo* fundInfo = WTSPortFundInfo::create();
    WTSFundStruct& fund = fundInfo->fundInfo();
    
    // 测试零值
    fund._balance = 0.0;
    fund._profit = 0.0;
    fund._dynprofit = 0.0;
    EXPECT_DOUBLE_EQ(fundInfo->balance(), 0.0);
    EXPECT_DOUBLE_EQ(fundInfo->profit(), 0.0);
    EXPECT_DOUBLE_EQ(fundInfo->dynprofit(), 0.0);
    
    // 测试负值
    fund._profit = -5000.0;
    fund._dynprofit = -2000.0;
    EXPECT_DOUBLE_EQ(fundInfo->profit(), -5000.0);
    EXPECT_DOUBLE_EQ(fundInfo->dynprofit(), -2000.0);
    
    // 测试极大值
    fund._balance = 1e12;  // 1万亿
    fund._max_dyn_bal = 1e15;  // 1千万亿
    EXPECT_DOUBLE_EQ(fundInfo->balance(), 1e12);
    EXPECT_DOUBLE_EQ(fundInfo->max_dyn_balance(), 1e15);
    
    // 测试初始极值状态
    WTSPortFundInfo* newFundInfo = WTSPortFundInfo::create();
    WTSFundStruct& newFund = newFundInfo->fundInfo();
    EXPECT_DOUBLE_EQ(newFund._max_dyn_bal, DBL_MAX);
    EXPECT_DOUBLE_EQ(newFund._min_dyn_bal, DBL_MAX);
    
    fundInfo->release();
    newFundInfo->release();
}

/*!
 * \brief 测试内存管理和对象生命周期
 * 
 * \details 验证对象的内存管理：
 *          - 对象创建和销毁
 *          - 引用计数管理
 *          - 内存泄漏检查
 */
TEST_F(WTSRiskPortfolioTest, TestMemoryManagement) {
    std::vector<WTSPortFundInfo*> fundInfos;
    std::vector<WTSCommodityInfo*> commodityInfos;
    std::vector<WTSContractInfo*> contractInfos;
    
    // 创建多个对象
    for (int i = 0; i < 100; ++i) {
        // 创建资金信息对象
        WTSPortFundInfo* fundInfo = WTSPortFundInfo::create();
        fundInfos.push_back(fundInfo);
        
        // 创建商品信息对象
        std::string pid = "TEST" + std::to_string(i);
        std::string name = "测试品种" + std::to_string(i);
        WTSCommodityInfo* commInfo = WTSCommodityInfo::create(
            pid.c_str(), name.c_str(), "TEST", "TRADING", "CHINA", "CNY"
        );
        commodityInfos.push_back(commInfo);
        
        // 创建合约信息对象
        std::string code = pid + "2412";
        std::string contractName = name + "2412";
        WTSContractInfo* contractInfo = WTSContractInfo::create(
            code.c_str(), contractName.c_str(), "TEST", pid.c_str()
        );
        contractInfos.push_back(contractInfo);
    }
    
    // 验证对象创建成功
    EXPECT_EQ(fundInfos.size(), 100);
    EXPECT_EQ(commodityInfos.size(), 100);
    EXPECT_EQ(contractInfos.size(), 100);
    
    // 清理资源
    for (auto* fundInfo : fundInfos) {
        fundInfo->release();
    }
    for (auto* commInfo : commodityInfos) {
        commInfo->release();
    }
    for (auto* contractInfo : contractInfos) {
        contractInfo->release();
    }
}

/*!
 * \brief 测试多线程安全性
 * 
 * \details 验证多线程环境下的对象访问：
 *          - 并发读取操作
 *          - 数据一致性
 *          - 线程安全性
 */
TEST_F(WTSRiskPortfolioTest, TestThreadSafety) {
    WTSPortFundInfo* fundInfo = WTSPortFundInfo::create();
    WTSFundStruct& fund = fundInfo->fundInfo();
    
    // 设置初始数据
    fund._balance = 100000.0;
    fund._profit = 5000.0;
    fund._dynprofit = 2000.0;
    
    const int num_threads = 4;
    const int operations_per_thread = 1000;
    std::vector<std::thread> threads;
    std::atomic<int> successful_reads(0);
    
    // 启动多个线程进行并发读取
    for (int i = 0; i < num_threads; ++i) {
        threads.emplace_back([&]() {
            for (int j = 0; j < operations_per_thread; ++j) {
                try {
                    // 并发读取操作
                    double balance = fundInfo->balance();
                    double profit = fundInfo->profit();
                    double dynprofit = fundInfo->dynprofit();
                    
                    // 验证数据一致性
                    if (balance == 100000.0 && profit == 5000.0 && dynprofit == 2000.0) {
                        successful_reads.fetch_add(1);
                    }
                } catch (...) {
                    // 捕获任何异常
                }
            }
        });
    }
    
    // 等待所有线程完成
    for (auto& t : threads) {
        t.join();
    }
    
    // 验证结果
    int expected_reads = num_threads * operations_per_thread;
    EXPECT_EQ(successful_reads.load(), expected_reads);
    
    fundInfo->release();
}

/*!
 * \brief 测试性能特性
 * 
 * \details 验证对象操作的性能：
 *          - 对象创建性能
 *          - 数据访问性能
 *          - 大量操作性能
 */
TEST_F(WTSRiskPortfolioTest, TestPerformanceCharacteristics) {
    const int num_objects = 10000;
    
    // 测试对象创建性能
    auto start = std::chrono::high_resolution_clock::now();
    
    std::vector<WTSPortFundInfo*> fundInfos;
    for (int i = 0; i < num_objects; ++i) {
        WTSPortFundInfo* fundInfo = WTSPortFundInfo::create();
        fundInfos.push_back(fundInfo);
    }
    
    auto end = std::chrono::high_resolution_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    std::cout << "创建 " << num_objects << " 个资金对象耗时: " << duration.count() << "ms" << std::endl;
    
    // 测试数据访问性能
    start = std::chrono::high_resolution_clock::now();
    
    double total_balance = 0.0;
    for (auto* fundInfo : fundInfos) {
        WTSFundStruct& fund = fundInfo->fundInfo();
        fund._balance = 100000.0 + (rand() % 10000);
        total_balance += fundInfo->balance();
    }
    
    end = std::chrono::high_resolution_clock::now();
    duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
    
    std::cout << "访问 " << num_objects << " 个资金对象耗时: " << duration.count() << "ms" << std::endl;
    
    // 清理资源
    for (auto* fundInfo : fundInfos) {
        fundInfo->release();
    }
    
    EXPECT_GT(total_balance, 0.0);
}

/*!
 * \brief 测试完整工作流程
 * 
 * \details 验证风控和资金管理的完整流程：
 *          - 资金初始化
 *          - 交易统计更新
 *          - 极值跟踪
 *          - 风控检查
 */
TEST_F(WTSRiskPortfolioTest, TestCompleteWorkflow) {
    // 1. 创建组合资金信息
    WTSPortFundInfo* fundInfo = WTSPortFundInfo::create();
    WTSFundStruct& fund = fundInfo->fundInfo();
    
    // 2. 初始化资金状态
    fund._prebalance = 1000000.0;    // 昨日静态权益
    fund._predynbal = 1020000.0;     // 昨日动态权益
    fund._balance = 1000000.0;       // 当前静态权益
    fund._profit = 0.0;              // 平仓盈亏
    fund._dynprofit = 0.0;           // 浮动盈亏
    fund._fees = 0.0;                // 手续费
    fund._last_date = 20241130;      // 上次结算日
    
    // 3. 创建商品和合约信息
    WTSCommodityInfo* commInfo = WTSCommodityInfo::create(
        "IF", "沪深300股指期货", "CFFEX", "TRADING", "CHINA", "CNY"
    );
    commInfo->setVolScale(300);
    commInfo->setPriceTick(0.2);
    commInfo->setCategory(CC_Future);
    
    WTSContractInfo* contractInfo = WTSContractInfo::create(
        "IF2412", "沪深300股指期货2412", "CFFEX", "IF"
    );
    contractInfo->setVolumeLimits(100, 500);
    
    // 4. 模拟交易过程
    TradeStatInfo statInfo;
    
    // 模拟开仓交易
    statInfo.l_openvol = 10;       // 多头开仓10手
    fund._profit += 1000.0;          // 平仓盈亏增加
    fund._dynprofit += 2000.0;       // 浮动盈亏增加
    fund._fees += 50.0;              // 手续费增加
    
    // 更新动态权益
    double current_dynbal = fund._balance + fund._profit + fund._dynprofit;
    
    // 更新极值
    if (fund._max_dyn_bal == DBL_MAX || current_dynbal > fund._max_dyn_bal) {
        fund._max_dyn_bal = current_dynbal;
        fund._max_time = 143000;  // 14:30:00
    }
    
    if (fund._min_dyn_bal == DBL_MAX || current_dynbal < fund._min_dyn_bal) {
        fund._min_dyn_bal = current_dynbal;
        fund._min_time = 143000;
    }
    
    // 5. 验证工作流程结果
    EXPECT_DOUBLE_EQ(fundInfo->balance(), 1000000.0);
    EXPECT_DOUBLE_EQ(fundInfo->profit(), 1000.0);
    EXPECT_DOUBLE_EQ(fundInfo->dynprofit(), 2000.0);
    EXPECT_DOUBLE_EQ(fundInfo->fees(), 50.0);
    EXPECT_DOUBLE_EQ(fundInfo->max_dyn_balance(), current_dynbal);
    EXPECT_EQ(fundInfo->max_dynbal_time(), 143000);
    
    EXPECT_EQ(statInfo.l_openvol, 10);
    EXPECT_STREQ(commInfo->getName(), "沪深300股指期货");
    EXPECT_STREQ(contractInfo->getCode(), "IF2412");
    EXPECT_EQ(contractInfo->getMaxMktVol(), 100);
    
    std::cout << "风控和资金管理完整工作流程测试通过" << std::endl;
    std::cout << "当前动态权益: " << current_dynbal << std::endl;
    std::cout << "开仓统计: " << statInfo.l_openvol << " 手" << std::endl;
    std::cout << "合约信息: " << contractInfo->getFullCode() << std::endl;
    
    // 清理资源
    fundInfo->release();
    commInfo->release();
    contractInfo->release();
} 